/*******************************************************************************
 * Copyright (c) 2010 European Software Institute - Tecnalia.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Author - Adri�n Noguero (adrian.noguero@esi.es)
 *     
 *******************************************************************************/
package es.esi.gemde.vv.masttool.constraints;

import java.util.Vector;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;

import es.esi.gemde.modelvalidator.service.IModelValidatorConstraint;
import es.esi.gemde.vv.mast.mastmodel.Bursty_External_Event;
import es.esi.gemde.vv.mast.mastmodel.ModelPackage;
import es.esi.gemde.vv.mast.mastmodel.Periodic_External_Event;
import es.esi.gemde.vv.mast.mastmodel.Regular_Transaction;
import es.esi.gemde.vv.mast.mastmodel.Singular_External_Event;
import es.esi.gemde.vv.mast.mastmodel.Sporadic_External_Event;
import es.esi.gemde.vv.mast.mastmodel.Unbounded_External_Event;
import es.esi.gemde.vv.masttool.MastToolPlugin;
import es.esi.gemde.vv.masttool.resources.utils.MASTModelingUtils;

/**
 * Implementation of the consistency check #7 of MAST.
 * Done directly in Java.
 *
 * @author Adrian Noguero (adrian.noguero@tecnalia.com)
 * @version 1.0
 * @since 1.0
 *
 */
public class ConsistencyCheck07 implements IModelValidatorConstraint {

	// Constants
	private static final String CATEGORY = "MAST Consistency Checks";
	private static final String NAME = "07 - No circular dependencies in the transaction graph";
	
	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#getBody()
	 */
	@Override
	public String getBody() {
		// Not used
		return "Constraint implemented in Java";
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#getCategory()
	 */
	@Override
	public String getCategory() {
		return CATEGORY;
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#getName()
	 */
	@Override
	public String getName() {
		return NAME;
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#getSeverity()
	 */
	@Override
	public int getSeverity() {
		return IStatus.ERROR;
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#isProtected()
	 */
	@Override
	public boolean isProtected() {
		return true;
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#getApplicationContext()
	 */
	@Override
	public EClass getApplicationContext() {
		return ModelPackage.eINSTANCE.getRegular_Transaction();
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#getApplicationMetamodel()
	 */
	@Override
	public EPackage getApplicationMetamodel() {
		return ModelPackage.eINSTANCE.getRegular_Transaction().getEPackage();
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#targetsTypeOf(org.eclipse.emf.ecore.EObject)
	 */
	@Override
	public boolean targetsTypeOf(EObject target) {
		return (target instanceof Regular_Transaction);
	}

	/* (non-Javadoc)
	 * @see es.esi.gemde.modelvalidator.service.IModelValidatorConstraint#validate(org.eclipse.emf.ecore.EObject)
	 */
	@Override
	public IStatus validate(EObject onTarget) {
		
		// Validate only for a valid object
		if (onTarget instanceof Regular_Transaction) {
			Regular_Transaction t = (Regular_Transaction)onTarget;
			
			// Get the external event list, as they are the inputs of the graph
			Vector<String> externalEvents = new Vector<String>();
			for (Bursty_External_Event e : t.getBursty_External_Event()) {
				externalEvents.add(e.getName());
			}
			for (Periodic_External_Event e : t.getPeriodic_External_Event()) {
				externalEvents.add(e.getName());
			}
			for (Singular_External_Event e : t.getSingular_External_Event()) {
				externalEvents.add(e.getName());
			}
			for (Sporadic_External_Event e : t.getSporadic_External_Event()) {
				externalEvents.add(e.getName());
			}
			for (Unbounded_External_Event e : t.getUnbounded_External_Event()) {
				externalEvents.add(e.getName());
			}
			
			
			// For each event we create a graph using a Tree
			for (String e : externalEvents) {
				if (MASTModelingUtils.createTree(e, t) == null) {
					return new Status(IStatus.ERROR, MastToolPlugin.PLUGIN_ID, "Circular dependency detected for transaction " + t.getName());
				}
			}
			
		}
		
		return new Status(IStatus.OK, MastToolPlugin.PLUGIN_ID, null);
	}

	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getIdentifier() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ResourceType getResourceType() {
		return ResourceType.PROTECTED;
	}
	

}
